#include "GameMainScene.h"
#include "MenuScene.h"
#include "EnemyBullet.h"
#include "SimpleAudioEngine.h"
#include "GameKey.h"
#include "json/json.h"
#include <iosfwd>
#include "Util/Util.h"


GameMainScene::GameMainScene() : m_score(0), m_enemy_num(0), m_isGameOver(false)
{

}

GameMainScene::~GameMainScene()
{
	hero->release();
	m_scoreLabelAtlas->release();
	m_hero_bullets->release();
	m_enemy->release();
	m_gameOver->release();

}


bool GameMainScene::init()
{
	if (!CCLayer::init())
	{
		return false;
	}



	CCSpriteBatchNode* bgNode = CCSpriteBatchNode::create("bg3.jpg");
	this->addChild(bgNode);

	CCSize size = CCDirector::sharedDirector()->getWinSize();
	bg1 = CCSprite::create("bg3.jpg");
	bg1->setPosition(ccp(size.width / 2, 0));
	bg1->setScaleX(0.5);
	bg1->setAnchorPoint(ccp(0.5, 0));
	bgNode->addChild(bg1, 0, EGameMainSceneTagBg1);

	bg2 = CCSprite::create("bg3.jpg");
	bg2->setPosition(ccp(size.width / 2, size.height *2 ) );
	bg2->setScaleX(0.5);
	bg2->setAnchorPoint(ccp(0.5, 0));
	bgNode->addChild(bg2, 0, EGameMainSceneTagBg2);


	CocosDenshion::SimpleAudioEngine::sharedEngine()->stopBackgroundMusic();
	CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadBackgroundMusic("zhandou.mp3");
	CocosDenshion::SimpleAudioEngine::sharedEngine()->preloadEffect(CCFileUtils::sharedFileUtils()->fullPathForFilename("bloser.mp3").c_str());
	CocosDenshion::SimpleAudioEngine::sharedEngine()->setEffectsVolume(0.5);
	

	CCMenuItemImage* back = CCMenuItemImage::create("backA.png", "backB.png", this, menu_selector(GameMainScene::menuBackCallBack));
	back->setPosition(ccp(size.width-20, size.height-20));
	back->setScale(0.5);
	CCMenu* menu = CCMenu::create(back, NULL);
	menu->setPosition(ccp(0, 0));
	this->addChild(menu, 2, EGameMainSceneTagBack);


	CCSpriteBatchNode* bloodNode = CCSpriteBatchNode::create("success_star.png");
	this->addChild(bloodNode);


	CCSprite* bgLiveLine = CCSprite::create("uiimg4.png");
	bgLiveLine->setAnchorPoint(ccp(0, 0.5));
	bgLiveLine->setPosition(ccp(0, size.height - 5));
	this->addChild(bgLiveLine);
	bgLiveLine->setScaleX(0.5);
	bgLiveLine->setScaleY(0.8);

	CCSprite* liveLine = CCSprite::create("uiimg5.png");
	processTimer = CCProgressTimer::create(liveLine);
	processTimer->setAnchorPoint(ccp(0, 0.5));
	processTimer->setPosition(ccp(0, size.height - 5));
	processTimer->setType(kCCProgressTimerTypeBar);
	processTimer->setMidpoint(ccp(0, 0));
	processTimer->setScaleX(0.5);
	processTimer->setScaleY(0.8);
	processTimer->setBarChangeRate(ccp(1, 0));
	this->addChild(processTimer);

	hero = Hero::create();
	//hero->setAnchorPoint(ccp(0.5, 0.5));
	hero->setPosition(ccp(size.width / 2, 40));
	hero->retain();
	this->addChild(hero,1);

	CCSprite* scoreTitle = CCSprite::create("score.png");
	scoreTitle->setScale(0.5);
	scoreTitle->setAnchorPoint(ccp(0, 0.5));
	scoreTitle->setPosition(ccp(0, size.height - 30));
	this->addChild(scoreTitle, 1);

	char ch[50];
	sprintf( ch, "%d", m_score);
	m_scoreLabelAtlas = CCLabelAtlas::create(ch, "num.png", 23, 25, '0');
	m_scoreLabelAtlas->setPosition(ccp(scoreTitle->getContentSize().width/2 + 2, size.height - 30));
	m_scoreLabelAtlas->setScale(0.5);
	m_scoreLabelAtlas->setAnchorPoint(ccp( 0, 0.5));
	m_scoreLabelAtlas->retain();
	this->addChild(m_scoreLabelAtlas, 3 );

	m_hero_bullets = CCArray::createWithCapacity(30);
	for (unsigned int i = 0; i < m_hero_bullets->capacity(); i++ )
	{
		HeroBullet* bullet = HeroBullet::create();
		bullet->setPosition(ccp(0, 0));
		bullet->setVisible(false);
		this->addChild(bullet, 1);
		m_hero_bullets->addObject(bullet);
	}
	m_hero_bullets->retain();

	this->scheduleUpdate();
	schedule(schedule_selector(GameMainScene::releaseBullets), 0.2f);

	
	m_enemy = CCArray::createWithCapacity(20);
	for (unsigned int i = 0; i < m_enemy->capacity(); i++)
	{
		Enemy* enemy = Enemy::create();
		enemy->setVisible(false);
		enemy->setPosition(size.width / 2, size.height + 40);
		enemy->setId(i);
		m_enemy->addObject(enemy);
		this->addChild(enemy);

		CCArray* enemyBullets = enemy->getEnemyBullet();
		if (enemyBullets)
		{
			for (unsigned int i = 0; i < enemyBullets->count(); i++)
			{
				auto enemyBullet = (EnemyBullet*)enemyBullets->objectAtIndex(i);
				if (enemyBullet)
				{
					enemyBullet->setPosition(ccp(size.width / 2, size.height));
					enemyBullet->setVisible(false);
					enemyBullet->setRelease(false);
					this->addChild(enemyBullet);
				}
			}
		}

	}
	m_enemy->retain();

	m_gameOver = CCSprite::create("gameover.png");
	m_gameOver->setPosition(ccp(size.width / 2, size.height / 2 + 40));
	m_gameOver->setScale(0.5);
	this->addChild(m_gameOver,4);
	m_gameOver->retain();
	m_gameOver->setVisible(false);

	m_scoreLabel = CCLabelTTF::create( "", "Marker Felt", 24);
	m_scoreLabel->setVisible(false);
	m_scoreLabel->setPosition(ccp(size.width / 2, size.height / 2 - 30)),
	this->addChild(m_scoreLabel,4);

	CCMenuItemImage* backToMenu = CCMenuItemImage::create("back.png", "back.png",this, menu_selector(GameMainScene::menuBackCallBack));
	backToMenu->setPosition(ccp(size.width / 2, size.height / 2 - 100));
	backToMenu->setScale(0.5);
	CCMenu* gameOverMenu = CCMenu::create(backToMenu, NULL);
	gameOverMenu->setPosition(ccp(0, 0));
	gameOverMenu->setVisible(false);
	this->addChild(gameOverMenu, 4  , EGameMainSceneTagMenu);
	schedule(schedule_selector(GameMainScene::enemyAttack), 0.6f);

	schedule(schedule_selector(GameMainScene::releaseEnemyBullets), 0.8f);

	return true;

}

void GameMainScene::onEnter()
{
	CCLayer::onEnter();
	CCSize size = CCDirector::sharedDirector()->getWinSize();
	
	CCMenu* menu = (CCMenu*)(this->getChildByTag(EGameMainSceneTagBack));
	if ( menu )
	{
		CCArray* pArray =  menu->getChildren();
		for (unsigned int i = 0; i < pArray->count(); i++)
		{
			CCMenuItemImage* menuItem = (CCMenuItemImage*)(pArray->objectAtIndex(i));
			if (menuItem)
			{
				menuItem->setPosition(ccp(size.width + 20, size.height - 20));
				menuItem->runAction(CCEaseBackOut::create(CCMoveTo::create(0.5, ccp(size.width - 20, size.height - 20))));
			}
		}
	}

	if (hero)
	{
		hero->setPosition(ccp(size.width / 2, -40));
		hero->runAction(CCMoveTo::create(0.8, ccp(size.width / 2, 40)));
	}
	if ( MenuScene::m_isSound )
	{
		CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("zhandou.mp3", true);
	}
	
	if ( hero )
	{
		setBloodProcess(hero->getBlood());
	}
}

void GameMainScene::onExit()
{
	CCLayer::onExit();
}


void GameMainScene::menuBackCallBack(CCObject* pSender)
{
	CCScene* pScene = MenuScene::scene();
	CCDirector::sharedDirector()->replaceScene(pScene);
}

CCScene* GameMainScene::scene()
{
	CCScene* pScene = CCScene::create();
	CCLayer* pLayer = GameMainScene::create();
	pScene->addChild(pLayer);
	return pScene;

}

void GameMainScene::bg1MoveToCallBack(CCNode* pSeneder)
{
	CCSize size = CCDirector::sharedDirector()->getWinSize();
	CCSprite* bg2 = (CCSprite*)(this->getChildByTag(EGameMainSceneTagBg2));
	bg2->setPosition(ccp(size.width / 2, 0));
	bg2->runAction(CCSequence::create(CCMoveTo::create(3, ccp(size.width / 2, size.height)), CCCallFuncN::create(this, callfuncN_selector(GameMainScene::bg2MoveToCallBack)), NULL));

}
void GameMainScene::bg2MoveToCallBack(CCNode* pSeneder)
{
	CCSize size = CCDirector::sharedDirector()->getWinSize();
	//CCSprite* bg1 = (CCSprite*)(this->getChildByTag(EGameMainSceneTagBg1));
	bg1->setPosition(ccp(size.width / 2, 0));
	bg1->runAction(CCSequence::create(CCMoveTo::create(3, ccp(size.width / 2, size.height)), CCCallFuncN::create(this, callfuncN_selector(GameMainScene::bg1MoveToCallBack)), NULL));

}

void GameMainScene::update(float date)
{

	CCSize size = CCDirector::sharedDirector()->getWinSize();
	int y1 = bg1->getPosition().y;	
	int y2 = bg2->getPosition().y;
	y1 -= 2;
	y2 -= 2;
	bg1->setPosition(ccp(size.width / 2, y1 ));
	bg2->setPosition(ccp(size.width / 2, y2));

	if ( y1 <= ( size.height * -2) )
	{
		bg1->setPosition(ccp(size.width / 2, size.height * 2));
	}

	if (y2 <= (size.height * -2))
	{
		bg2->setPosition(ccp(size.width / 2, size.height * 2));
	}

	if (m_isGameOver)
	{
		return;
	}
	m_enemy_num = 0;
	for (unsigned int i = 0; i < m_enemy->count(); i++)
	{
		Enemy* enemy = (Enemy*)m_enemy->objectAtIndex(i);
		if (!enemy)
		{
			continue;
		}
		if (enemy->isLife())
		{
			m_enemy_num++;
			if (hero->isWudi() )
			{
				continue;
			}

			if (enemy->boundingBox().intersectsRect(hero->boundingBox()))
			{

				hero->setHurt();
				enemy->setDie();
				m_enemy_num--;
				m_score++;
				char ch[50];
				sprintf(ch, "%d", m_score);
				m_scoreLabelAtlas->setString(ch);
				if (hero)
				{
					setBloodProcess(hero->getBlood());
				}
				int blood = hero->getBlood();
				if ( blood < 1 )
				{
					setGameOver();
				}
			}

			CCArray* enemyBullets = enemy->getEnemyBullet();
			if (enemyBullets)
			{
				for (unsigned int i = 0; i < enemyBullets->count(); i++)
				{
					auto enemyBullet = (EnemyBullet*)enemyBullets->objectAtIndex(i);
					if (!enemyBullet)
					{
						continue;
					}
					if (!enemyBullet->isRelease())
					{
						continue;
					}
					if ( enemyBullet->boundingBox().intersectsRect( hero->boundingBox()))
					{
				//	}
				//	if (isInRect(enemyBullet, hero))
				//	{
						hero->setHurt();
						setBloodProcess(hero->getBlood());
						enemyBullet->setVisible(false);
						enemyBullet->setRelease(false);
						int blood = hero->getBlood();
						if (blood < 1)
						{
							setGameOver();
						}
					}

				}
			}
		}
	}

	for (unsigned int i = 0; i < m_hero_bullets->count(); i++)
	{
		HeroBullet* bullet = (HeroBullet*)m_hero_bullets->objectAtIndex(i);
		if (!bullet->isRelease())
		{
			continue;
		}
		for (unsigned int i = 0; i < m_enemy->count(); i++)
		{
			Enemy* enemy = (Enemy*)m_enemy->objectAtIndex(i);
			if (!enemy)
			{
				continue;
			}
			if (!enemy->isLife())
			{
				continue;
			}
			if (bullet->boundingBox().intersectsRect(enemy->boundingBox()))
			{
				enemy->setDie();
				if ( MenuScene::m_isSound )
				{
					CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(CCFileUtils::sharedFileUtils()->fullPathForFilename("bloser.mp3").c_str());
				}
				m_enemy_num--;
				m_score++;
				char ch[50];
				sprintf(ch, "%d", m_score);
				m_scoreLabelAtlas->setString(ch);
				bullet->setRelease(false);
				bullet->setVisible(false);
				bullet->stopAllActions();
				
				break;
			}
		}
	}
}

void GameMainScene::releaseBullets(float dt)
{
	if ( !hero || !m_hero_bullets )
	{
		return;
	}
	if ( hero->getBlood() < 1 )
	{
		return;
	}
	CCPoint point = hero->getPosition();
	CCSize size = CCDirector::sharedDirector()->getWinSize();

	for (unsigned int i = 0; i < m_hero_bullets->count(); i++ )
	{
		HeroBullet* bullet = (HeroBullet*)m_hero_bullets->objectAtIndex(i);
		if (bullet && !bullet->isRelease() )
		{
			bullet->setRelease(true);
			bullet->setVisible(true);
			bullet->setPosition(ccp(point.x, point.y + hero->getContentSize().height /2 + bullet->getContentSize().height /2 ));
			bullet->runAction(CCSequence::create(CCMoveTo::create((size.height - point.y) / 240, ccp(point.x, size.height)), CCCallFuncN::create(bullet, callfuncN_selector(GameMainScene::releaseBulletsCallBack)), NULL));
			break;
		}
	}

}

void GameMainScene::releaseBulletsCallBack(CCNode* pSeneder)
{
	if (!pSeneder)
	{
		return;
	}
	HeroBullet* bullet = (HeroBullet*)pSeneder;
	if ( bullet )
	{
		bullet->setVisible(false);
		bullet->setRelease(false);
		bullet->stopAllActions();
	}

}

bool  GameMainScene::isInRect(CCNode* node1, CCNode* node2)
{
	CCSize size1 = node1->getContentSize();
	CCSize size2 = node2->getContentSize();

	CCPoint t1 = node1->getPosition();
	CCPoint t2 = node2->getPosition();

	return abs(t1.x - t2.x) <= (size1.width / 2 + size2.width / 2) && abs(t1.y - t2.y) <= (size1.height / 2 + size2.height / 2);

}


void GameMainScene::enemyAttack(float dt )
{
	for ( unsigned int i = 0; i < m_enemy->count(); i++)
	{
		if (m_enemy_num >= 6 )
		{
			break;
		}
		Enemy* enemy = (Enemy*)m_enemy->objectAtIndex(i);
		if (enemy->isLife())
		{
			continue;
		}
		m_enemy_num++;
		enemy->setDogShow(true);
		enemy->setVisible(true);
		enemy->setLife(true);
		int type = rand() % 4;
		enemy->setType(type);
		enemy->move(  hero->getPosition() );
	}

}

void GameMainScene::setHurt()
{
	if (!hero )
	{
		return;
	}
	
	hero->stopAllActions();
	hero->runAction(CCBlink::create(1.5f, 3));
}

void GameMainScene::setGameOver()
{
	m_isGameOver = true;
	for (unsigned int i = 0; i < m_hero_bullets->count(); i++)
	{
		HeroBullet* bullet = (HeroBullet*)(m_hero_bullets->objectAtIndex(i));
		if (bullet)
		{
			bullet->setVisible(false);
			bullet->setRelease(false);
			bullet->stopAllActions();
		}
	}




	CCMenu* menu = (CCMenu*)( this->getChildByTag(EGameMainSceneTagMenu));
	if ( menu )
	{
		menu->setVisible(true);
	}
	if ( m_gameOver )
	{
		m_gameOver->setVisible(true);
		m_gameOver->runAction(CCScaleTo::create(0.5,0.5));
	}
	for (unsigned int i = 0; i < m_enemy->count(); i++)
	{
		Enemy* enemy = (Enemy*)(m_enemy->objectAtIndex(i));
		if ( enemy )
		{
			enemy->stopAllActions();
			enemy->setLife(false);
		}
	}
	int maxScroe = CCUserDefault::sharedUserDefault()->getIntegerForKey(GAME_KEY_MAX_SCORE.c_str(), 0);
	if (maxScroe < m_score)
	{
		maxScroe = m_score;
		CCUserDefault::sharedUserDefault()->setIntegerForKey(GAME_KEY_MAX_SCORE.c_str(), m_score);
	}

	if ( m_scoreLabel )
	{

		//Json::Value json;
		//JsonManager::instance()->getJsonFromFile("stringKey.json",json);
		//CCString* showStr = CCString::createWithFormat("%s%d\n\n%s%d", json["thisSroce"].asString().c_str(), m_score, json["maxScore"].asString().c_str(), maxScroe);
		//std::string showString = showStr->getCString();
		//Util::Gbk2Utf8(showString);

		//CCDictionary *strings = CCDictionary::createWithContentsOfFile("fonts/strings.xml");

		//const char *titleStr = (CCString*)strings->objectForKey("title")->m_sString.c_str();

		CCDictionary *showStrs = CCDictionary::createWithContentsOfFile("fonts/StringKey.xml");
		const char* thisScrosStr = ((CCString*)(showStrs->objectForKey("thisSroce")))->getCString();
		const char* maxScrosStr = ((CCString*)(showStrs->objectForKey("maxScore")))->getCString();
		CCString* showStr = CCString::createWithFormat("%s%d\n\n%s%d", thisScrosStr, m_score, maxScrosStr, maxScroe);

		m_scoreLabel->setString(showStr->getCString());
		CC_SAFE_DELETE(showStr);
		m_scoreLabel->setVisible(true);
	}
}


void  GameMainScene::releaseEnemyBullets(float dt)
{
	if (!m_enemy)
	{
		return;
	}
	if ( m_isGameOver )
	{
		return;
	}

	for (unsigned int i = 0; i < m_enemy->count(); i++)
	{
		Enemy* enemy = (Enemy*)(m_enemy->objectAtIndex(i));
		if (!enemy)
		{
			continue;
		}
		if ( !enemy->isLife())
		{
			continue;
		}

		CCArray* enemyBullets = enemy->getEnemyBullet();
		if (enemyBullets)
		{
			int bulletNum = 0;
			for (unsigned int i = 0; i < enemyBullets->count(); i++)
			{
				if (bulletNum >= 2 )
				{
					break;
				}
				auto enemyBullet = (EnemyBullet*)enemyBullets->objectAtIndex(i);
				if ( !enemyBullet)
				{
					continue;
				}
				if (enemyBullet->isRelease())
				{
					bulletNum++;
					continue;
				}
				enemyBullet->setPosition(ccp(enemy->getPosition().x, enemy->getPosition().y - 40 ));
				enemyBullet->setVisible(true);
				enemyBullet->setRelease(true);

				CCMoveTo* moveTo1 = CCMoveTo::create(enemy->getPosition().y / 300, ccp(enemy->getPosition().x, -40));
				CCMoveTo* moveTo2 = CCMoveTo::create(enemy->getPosition().y / 300, ccp(hero->getPosition().x, -40));

				int type = rand() % 2;
				if ( type )
				{
					enemyBullet->runAction(CCSequence::create(moveTo1, CCCallFuncN::create(enemyBullet, callfuncN_selector(GameMainScene::releaseEnemyBulletsCallBack)), NULL));
				}
				else
				{
					enemyBullet->runAction(CCSequence::create(moveTo1, CCCallFuncN::create(enemyBullet, callfuncN_selector(GameMainScene::releaseEnemyBulletsCallBack)), NULL));
				}

				bulletNum++;
				break;
			}
		}

	}
}
void  GameMainScene::releaseEnemyBulletsCallBack(CCNode* pSender)
{
	auto enemyBullet = (EnemyBullet*)pSender;
	if (!enemyBullet)
	{
		return;
	}
	enemyBullet->setVisible(false);
	enemyBullet->setRelease(false);
}

void GameMainScene::setBloodProcess(int blood)
{
	if ( !processTimer )
	{
		return;
	}

	float newProcess = blood  * 100.0f / GAME_KEY_HERO_MAX_BLOOD;
	float process = processTimer->getPercentage();

	CCProgressFromTo* to = CCProgressFromTo::create( 0.2f, process, newProcess );
	processTimer->runAction(to);
}
